﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;


namespace BenevolentSun
{
    public class Camera
    {
        Matrix view;
        public Matrix View
        {
            get { return view; }
        }

        Matrix proj;
        public Matrix Proj
        {
            get { return proj; }
        }

        // vectors
        Vector3 lookAt;
        public Vector3 LookAt
        {
            get { return lookAt; }
        }

        Vector3 up = new Vector3(0.0f, 1.0f, 0.0f);
        public Vector3 Up
        {
            get { return up; }
            set { up = value; invalid = true; }
        }

        // positions
        Vector3 eye;
        public Vector3 Eye
        {
            get { return eye; }
            set { eye = value; invalid = true; }
        }

        Vector3 at;
        public Vector3 At
        {
            get { return at; }
            set { at = value; invalid = true; }
        }

        float fov;
        public float Fov
        {
            get { return fov; }
            set { fov = value; invalid = true; }
        }

        float nearPlane;
        public float NearPlane
        {
            get { return nearPlane; }
            set { nearPlane = value; invalid = true; }
        }

        float farPlane;
        public float FarPlane
        {
            get { return farPlane; }
            set { farPlane = value; invalid = true; }
        }

        bool invalid = true;

        bool changed = false;
        public bool Changed
        {
            get { return changed; }
        }

        public GraphicsDevice Device;


        public Camera(GraphicsDevice device, Vector3 eye, Vector3 at, float near, float far, float fov)
        {
            Device = device;
            this.eye = eye;
            this.at = at;

            nearPlane = near;
            farPlane = far;
            this.fov = fov;
        }

        public void Update()
        {
            if (invalid)
            {
                Matrix.CreateLookAt(
                    ref eye,
                    ref at,
                    ref up,
                    out view);

                Matrix.CreatePerspectiveFieldOfView(
                    fov,                                            // fov
                    Device.Viewport.AspectRatio,                    // aspect
                    nearPlane,                                      // near clip
                    farPlane,                                      // far clip
                    out proj);

                lookAt = at - eye;
                lookAt.Normalize();

                invalid = false;
                changed = true;
            }
            else
            {
                changed = false;
            }
        }

        public void MoveForward()
        {
            eye.X += (LookAt.X);
            eye.Z += (LookAt.Z);
            invalid = true;
        }

        public void OrientationMove(Vector2 delta)
        {
            at.X += delta.X;
            at.Z -= delta.Y;

            eye.X += delta.X;
            eye.Z -= delta.Y;
            invalid = true;
        }

    }
}
